package api

import (
	"context"
	"errors"
	"fmt"
	"longmen/server/config/global"
	global2 "longmen/server/config/global"
	"longmen/server/internal/services/consumers/publisher"
	_const "longmen/server/pkg/common/helper/const"
	string2 "longmen/server/pkg/common/helper/string"
	"longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/common/sdk/tx"
	"longmen/server/pkg/db/mysql"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/mysql/models/models_main"
	cache2 "longmen/server/pkg/db/redis/cache"
	"longmen/server/pkg/grpc_client"
	"longmen/server/pkg/protobuf"
	"strings"
	"time"

	"longmen/server/pkg/common/api_models"

	"github.com/labstack/echo/v4"
	"github.com/spf13/cast"
	"google.golang.org/grpc/status"
	"gorm.io/gorm"
)

// UpdateNickName 修改昵称
// @Summary 修改昵称
// @Description 修改昵称
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.ProfileRequest true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/updateNickName [POST]
func (base *Controller) UpdateNickName(c echo.Context) error {
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	req := &protobuf.UpdateNickNameReq{}

	if err := util.Json2Struct(c.Get("body").(string), &req); err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	if err := _const.Validate.Struct(req); err != nil {
		return util.BadParam(c, err)
	}
	req.Uid = int64(user.Id)
	//err = base.Service.CheckCode(user.Mobile, req.SmsCode)
	//if err != nil {
	//	return common.BuildFail(c, 1, err.Error(), err)
	//}
	///grpc
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.UpdateNickName(ctx, req)
	if err != nil {
		return util.BuildFail(c, 1, err.Error(), err)
	}
	err = cache2.OnTaskEvent(int(user.Id), _const.TASK_SET_NICKNAME, 1)
	if err != nil {
		global2.Log.Infof("任务:用户%d 改名事件推送失败，任务id%d", user.Id, int(_const.TASK_SET_NICKNAME), err.Error())
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 上傳圖片
// @Description 上傳圖片
// @Accept  json
// @Produce  json
// @Tags User
// @Router /api/user/file [POST]
func (base *Controller) Upload(c echo.Context) error {
	global.Log.Debugf("Upload:", c)
	form, err := c.MultipartForm()
	if err != nil {
		return util.BadParam(c, err)
	}
	fs := form.File["file"]
	var previews []string
	//todo:上传地址改到桶里
	for i, file := range fs {
		if i >= 9 {
			break
		}
		switch file.Header.Get("Content-Type") {
		case "image/gif", "image/png", "image/jpeg", "image/bmp", "image/webp", "image/jpg":
		default:
			return util.BuildFail(c, 1, "", errors.New("不支持的图片格式"))
		}
		fileReader, err := file.Open()
		filename, err := tx.UploadFile(file.Filename, fileReader)
		if err != nil {
			return util.BuildFail(c, 1, "", err)
		}
		previews = append(previews, filename)
	}
	return util.BuildSuccess(c, strings.Join(previews, ","), "")
}

func (base *Controller) UploadImg(c echo.Context) error {
	global.Log.Debugf("UploadImg:", c)
	form, err := c.MultipartForm()
	if err != nil {
		return util.BadParam(c, err)
	}
	fs := form.File["file"]

	return nil
	var previews []string
	//todo:上传地址改到桶里
	for i, file := range fs {
		if i >= 9 {
			break
		}
		switch file.Header.Get("Content-Type") {
		case "image/gif", "image/png", "image/jpeg", "image/bmp", "image/webp", "image/jpg":
		default:
			return util.BuildFail(c, 1, "", errors.New("不支持的图片格式"))
		}
		fileReader, err := file.Open()
		filename, err := tx.UploadFile(file.Filename, fileReader)
		if err != nil {
			return util.BuildFail(c, 1, "", err)
		}
		previews = append(previews, filename)
	}
	return util.BuildSuccess(c, strings.Join(previews, ","), "")
}

// @Summary 默认头像
// @Description 默认头像
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body protobuf.GetDefultAvatarsReq true "body"
// @Success 200 {object} models_main.Avatars "result"
// @Router /api/user/defaultAvatar [POST]
func (base *Controller) GetDefultAvatars(c echo.Context) error {
	r := &protobuf.GetDefultAvatarsReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.GetDefultAvatars(ctx, r)
	if err != nil {
		return util.BuildFail(c, 1, "", err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 注册第一步
// @Description 注册第一步
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.CheckVerifyCodeReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/regist [POST]
func (base *Controller) Regist(c echo.Context) error {
	//设备拉黑
	isBlack := CheckDeviceBlackDevice(base.GetDeviceInfo(c))
	if isBlack {
		return util.BuildFail(c, 1, global.Lang.T("restrict_register"), nil)
	}

	isBlack = CheckDeviceBlackIp(c.RealIP())
	if isBlack {
		return util.BuildFail(c, 1, global.Lang.T("restrict_register"), nil)
	}

	r := &protobuf.CheckVerifyCodeReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	r.Mobile = strings.ReplaceAll(r.Mobile, " ", "")
	err := util.CheckMobile(r.GetMobile())
	if err != nil {
		return util.BuildFail(c, 1, err.Error(), err)
	}
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.Regist(ctx, r)
	if err != nil {
		statsErr := status.Convert(err)
		return util.BuildFail(c, 1, statsErr.Message(), err)
	}
	return util.BuildSuccess(c, protobuf.CheckVerifyCodeResp{MobileHash: resp.GetMobileHash()}, "")
}

// @Summary 注册第二步
// @Description 注册第二步
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.RegisterReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/register [POST]
func (base *Controller) ExecRegister(c echo.Context) error {
	req := &api_models.RegisterReq{}
	req.Account = strings.ReplaceAll(req.Account, " ", "")
	if err := util.Json2Struct(c.Get("body").(string), req); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(req); err != nil {
		return util.BadParam(c, err)
	}
	global2.Log.Debugf("heardDevice:%v,bodyDevice:%v", base.GetDeviceInfo(c), req.DeviceInfo)
	r := &protobuf.RegisterReq{
		Account:    req.Account,
		Pwd:        req.Pwd,
		MobileHash: req.MobileHash,

		Platform: uint32(req.Platform),
		// Sex:      uint32(req.Sex),
		Sex: 1, // 产品需求默认男性

		InviteCode: req.InviteCode,
		Ip:         c.RealIP(),
		DeviceInfo: base.GetDeviceInfo(c), //req.DeviceInfo,

		Website:  req.Website,
		AnchorId: req.AnchorId,
	}
	switch req.RegSourceId.(type) { //动态类型
	case int, float64:
		r.RegSourceId = fmt.Sprint(req.RegSourceId)
	case string:
		r.RegSourceId = req.RegSourceId.(string)
	}
	//fixme Platform
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.ExecRegister(ctx, r)
	if err != nil {
		statsErr := status.Convert(err)
		return util.BuildFail(c, 1, statsErr.Message(), err)
	}

	util.SetCookie(c, "token", resp.Token)
	util.SetCookie(c, "uid", cast.ToString(resp.Id))
	err = cache2.SetUserToken(int(resp.Id), resp.Token, req.Platform)
	if err != nil {
		global2.Log.Errorf("set token error[%v]: ", err)
	}
	err = cache2.OnTaskEvent(int(resp.Id), _const.TASK_SIGN_UP, 1) //注册成功事件
	if err != nil {
		global2.Log.Infof("任务:推送注册事件失败%d, %d, %v", resp.Id, int(_const.TASK_SIGN_UP), err.Error())
	}
	if r.Platform != 0 { //
		err = cache2.OnTaskEvent(int(resp.Id), _const.TASK_SIGN_IN_APP, 1) //首次登陆app事件
		if err != nil {
			global2.Log.Infof("任务:推送App登陆事件失败%d领取活动ID:%d失败,%v", resp.Id, int(_const.TASK_SIGN_IN_APP), err.Error())
		}
		err = cache2.OnTaskEvent(int(resp.Id), _const.TASK_SIGN_IN_EVERYDAY, 1) //每日登陆app事件
		if err != nil {
			global2.Log.Infof("任务:推送App登陆事件失败%d领取活动ID:%d失败,%v", resp.Id, int(_const.TASK_SIGN_IN_EVERYDAY), err.Error())
		}
	}

	//抖音巨量转化
	dyTransform(req.DeviceInfo, uint32(req.Platform))

	// 推送使用统计
	err = global2.PublisherStatistic.StatisticPush(
		publisher.RegisterStatistic, int(resp.Id), req.DeviceInfo, c.RealIP(), int8(req.Platform),
	)
	if err != nil {
		global2.Log.Infof("stats error: %v", err)
	}
	//增加腾讯 sig 调用
	resp.Sig = getSig(ctx, int(resp.Id))

	// 弹窗统计
	var dr api_models.ActionReq
	util.Json2Struct(c.Get("body").(string), &dr)

	if dr.Desc != "" {
		var d models_main.DialogConfig
		err = global.GetR().Model(&d).Where("status=1").First(&d).Error
		if err != nil {
			global2.Log.Infof("dialog_config error: %v", err)
		}
		err = global.GetX().Model(&d).Where("id=?", d.ID).Update("reg_count", gorm.Expr("reg_count+1")).Error
		if err != nil {
			global2.Log.Infof("dialog_config error: %v", err)
		}
	}

	// 发观赛券
	if _, err := grpc_client.GrpcLiveServer.ProvideTicket(ctx, &protobuf.ProvideTicketReq{
		Uids:        []int64{int64(resp.Id)},
		Quantity:    3,
		ProvideType: 2,
	}); err != nil {
		global2.Log.Infof("ProvideTicket error: %v", err)
	}

	return util.BuildSuccess(c, resp, "")
}

func dyTransform(deviceInfo string, platform uint32) {
	trsReq := &api_models.AscribeTransformReq{
		EvenType: "active_register",
		AscribeReportBaseReq: api_models.AscribeReportBaseReq{
			Platform:           "android",
			IDFV:               "",
			AndroidId:          deviceInfo,
			CustomerActiveTime: time.Now().UnixMilli(),
			Callback:           "",
			Res:                "",
		},
	}
	global.Log.Debugf("抖音巨量转化, dyTransform:%v", trsReq)
	if platform == _const.LOGIN_PLATFORM_ANDROID {
		err := global2.PublishChannelStats.Send(publisher.RegisterDyTransform, trsReq)
		if err != nil {
			global2.Log.Debugf("抖音巨量转化, dyTransform:%v,err:%v", trsReq, err)
		}
	}
}

// @Summary 发送验证码
// @Description 发送验证码
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.SendCodeReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/sendCode [POST]
func (base *Controller) SendCode(c echo.Context) error {
	r := &api_models.SendCodeReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}

	r.Mobile = strings.ReplaceAll(r.Mobile, " ", "") // 去掉所有手机号中的空格
	// if r.Mobile == "" {
	// 	return util.BadParam(c, nil)
	// }
	if r.IsChangeMobile == 1 {
		if !base.Service.CheckUserIsExistByMobile(r.Mobile) {
			return util.BuildSuccess(c, nil, "")
		}
		//验证手机号
		user, err := mysql.GetUserParam(map[string]interface{}{"mobile": r.Mobile})
		if err != nil {
			return util.BuildSuccess(c, nil, "")
		}
		if user.Id <= 0 || user.Status == _const.ACCOUNT_DEACTIVED {
			return util.BuildSuccess(c, nil, "")
		}
	}
	if r.IsRegister == 1 {
		if base.Service.CheckUserIsExistByMobile(r.Mobile) {
			err := errors.New("您已经注册,请直接登录")
			return util.BuildFail(c, 1, err.Error(), err)
		}
	}
	ip := c.RealIP()
	if r.NationCode <= 0 {
		r.NationCode = 86
	}
	if cache2.SendSmsCodeLimit(ip, r.Mobile) {
		return util.BuildFail(c, 1, global.Lang.T("verification_code_sent_too_often"), nil)
	}
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.SendSmsCode(ctx, &protobuf.SendSmsCodeReq{
		AreaCode: cast.ToString(r.NationCode),
		Ip:       ip,
		Mobile:   r.Mobile,
	})
	if err != nil {
		return util.BuildFail(c, 1, global.Lang.T("send_failed"), err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 发送验证码 需登入
// @Description 发送验证码 需登入
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.SendVerifyCodeReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/sendVerifyCode [POST]
func (base *Controller) SendVerifyCode(c echo.Context) error {
	r := &api_models.SendVerifyCodeReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	ip := c.RealIP()
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	if r.IsChangeMobile == 1 {
		if r.Mobile != user.Mobile {
			return util.BuildFail(c, 1, "该手机号与当前登录账号不一致", nil)
		}
	}
	if cache2.SendSmsCodeLimit(ip, r.Mobile) {
		return util.BuildFail(c, 1, global.Lang.T("verification_code_sent_too_often"), nil)
	}

	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.SendSmsCode(ctx, &protobuf.SendSmsCodeReq{
		Ip:     ip,
		Mobile: r.Mobile,
	})
	if err != nil {
		return util.BuildFail(c, 1, "发送失败", err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 登入
// @Description 登入
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body protobuf.LoginReq true "进行登录需要的数据"
// @Success 0 object protobuf.LoginResp "成功返回结果"
// @Success 301   object  api_models.LoginRespSimplifiedRedirectResp  "未注册用户登录默认注册,重定向至第二步注册"
// @Router /api/user/login [POST]
func (base *Controller) Login(c echo.Context) error {
	r := &protobuf.LoginReq{}
	var err error
	if err = util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err = _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	//设备拉黑
	isBlack := CheckDeviceBlackDevice(base.GetDeviceInfo(c))
	if isBlack {
		return util.BuildFail(c, 1, global.Lang.T("restrict_login"), nil)
	}
	isBlack = CheckDeviceBlackIp(c.RealIP())
	if isBlack {
		return util.BuildFail(c, 1, global.Lang.T("restrict_login"), nil)
	}
	r.Account = strings.ReplaceAll(r.Account, " ", "")
	//使用黑名单设备注册的全部账户，在其他设备不可进行登陆
	isBlack = CheckAccountBlackDevice(r.Account)
	if isBlack {
		return util.BuildFail(c, 1, global.Lang.T("network_timeout"), nil)
	}
	global2.Log.Debugf("heardDevice:%v,bodyDevice:%v", base.GetDeviceInfo(c), r.DeviceInfo)
	r.Ip = c.RealIP()
	r.DeviceInfo = base.GetDeviceInfo(c)
	//fixme Platform
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.Login(ctx, r)
	if err != nil {
		statsErr := status.Convert(err)
		return util.BuildFail(c, 1, statsErr.Message(), err)
	}
	util.SetCookie(c, "token", resp.Token)
	util.SetCookie(c, "uid", cast.ToString(resp.Id))
	if resp.Id > 0 {
		if r.Platform != 0 {
			err = cache2.OnTaskEvent(int(resp.Id), _const.TASK_SIGN_IN_APP, 1)
			if err != nil {
				global2.Log.Infof("任务:用户%d Login事件推送失败，任务id%d", resp.Id, int(_const.TASK_SIGN_IN_APP), err.Error())
			}
			err = cache2.OnTaskEvent(int(resp.Id), _const.TASK_SIGN_IN_EVERYDAY, 1)
			if err != nil {
				global2.Log.Infof("任务:用户%d Login事件推送失败，任务id%d", resp.Id, int(_const.TASK_SIGN_IN_EVERYDAY), err.Error())
			}
		}
		if global2.PublisherStatistic != nil {
			// 推送使用统计
			err = global2.PublisherStatistic.StatisticPush(
				publisher.LoginApiStatistic, int(resp.Id), base.GetDeviceInfo(c), c.RealIP(), int8(r.Platform),
			)
			if err != nil {
				global2.Log.Errorf("stats error:%v", err)
			}
		}

		//增加腾讯 sig 调用
		resp.Sig = getSig(ctx, int(resp.Id))

		// 登录弹窗统计
		var dr api_models.ActionReq
		util.Json2Struct(c.Get("body").(string), &dr)

		if dr.Desc != "" {
			var d models_main.DialogConfig
			err = global.GetR().Model(&d).Where("status=1").First(&d).Error
			if err != nil {
				global2.Log.Infof("dialog_config error: %v", err)
			}
			err = global.GetX().Model(&d).Where("id=?", d.ID).Update("login_count", gorm.Expr("login_count+1")).Error
			if err != nil {
				global2.Log.Infof("dialog_config error: %v", err)
			}
		}

		return util.BuildSuccess(c, resp, "")
	}
	return util.BuildSuccessWithStatus(c,
		api_models.LoginRespSimplifiedRedirectResp{MobileHash: resp.GetMobileHash()},
		"请进行第二步注册!",
		_const.REDIRECT_CACHE)
}

// @Summary 登出 需登入
// @Description 登出 需登入
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 object  api_models.Response "result"
// @Router /api/user/logout [POST]
func (base *Controller) Logout(c echo.Context) error {
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}

	token := util.GetCookie(c, "token")
	cacheToken, err := cache2.GetUserTokenLua(user.Id)
	util.DelCookie(c, "token")
	util.DelCookie(c, "uid")
	err = cache2.DelUserToken(user.Id, token, cacheToken)
	if err != nil {
		global2.Log.Errorf("%s %s\n", util.Convert2(), err.Error())
	}
	//再次取token , 取到的值为, 表示两端都未有token
	cacheToken, err = cache2.GetUserTokenLua(user.Id)
	if strings.EqualFold(cacheToken, ",") {
		user.OnlineStatus = 9
		if err := base.Service.UpdateUser([]string{"online_status"}, user); err != nil {
			return util.BuildFail(c, 1, err.Error(), err)
		}
	}
	return util.BuildSuccess(c, nil, "登出成功")
}

// @Summary 获取用戶資料
// @Description 获取用戶資料
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 {object} protobuf.GetUserInfoResp "result"
// @Router /api/user/getUserInfo [POST]
func (base *Controller) GetUserInfo(c echo.Context) error {
	uid := c.Get("uid").(int)
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.GetUserInfo(ctx, &protobuf.GetUserInfoReq{Uid: uint64(uid)})
	if err != nil {
		statsErr := status.Convert(err)
		return util.BuildFail(c, 1, statsErr.Message(), err)
	}

	// 推送使用统计
	//err = global2.PublisherStatistic.StatisticPush(
	//	publisher.LoginStatistic, uid, base.GetDeviceInfo(c), c.RealIP(), base.GetPlatform(c),
	//)
	if err != nil {
		global2.Log.Errorf("stats error:%v", err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 修改個人資料
// @Description 修改個人資料
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.EditUserInfoReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/editUserInfo [POST]
func (base *Controller) EditUserInfo(c echo.Context) error {
	r := api_models.EditUserInfoReq{}
	if err := util.Json2Struct(c.Get("body").(string), &r); err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	if r == (api_models.EditUserInfoReq{}) { //判斷是空的就返回
		return util.BuildSuccess(c, nil, "")
	}

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	//去掉验证
	//if r.NickName != "" {
	//	err := base.Service.CheckCode(user.Mobile, r.SmsCode)
	//	if err != nil {
	//		return common.BuildFail(c, 1, err.Error(), err)
	//	}
	//}
	profile := &models_main.UserProfile{Uid: user.Id}
	user_col := make([]string, 0)
	userApply := new(models_main.UserApply)
	if r.AvatarId > 0 {
		avaterInfo, err := db_main.GetAdsParam(map[string]interface{}{"id": r.AvatarId}, "")
		if err != nil {
			return util.BuildFail(c, 1, "", err)
		}
		if avaterInfo.Id < 1 {
			return util.BuildFail(c, 1, fmt.Sprintf("头像配置有误%d,%s", r.AvatarId, err.Error()), err)
		}
		user.Avatar = avaterInfo.ImageUrl
		user_col = append(user_col, "avatar")
	}
	if len(r.NickName) > 0 {
		ctx, cancel := base.GrpcWithTimeout()
		defer cancel()
		_, err = grpc_client.GrpcAccountServer.UpdateNickName(ctx,
			&protobuf.UpdateNickNameReq{
				Nickname: r.NickName,
				Uid:      int64(user.Id),
			})
		if err != nil {
			return util.BuildFail(c, 1, err.Error(), err)
		}
		//if count > 0 {
		//	return common.BuildFail(c, 1, "您当前已有修改的昵称正在审核当中", nil)
		//}
		// user.PendingNickName = r.NickName
		// user.ApplyNameTime = timehelper.Now().Unix()
		// user_col = append(user_col, "pending_nick_name", "apply_name_time")
		userApply.UserID = user.Id
		userApply.ChangeType = 0   // default
		userApply.ChangeSource = 0 // default
		userApply.OriginalData = user.NickName
		userApply.NewData = r.NickName
		userApply.Status = 0
		userApply.CreatedAt = time.Now()

	}

	profile_col := make([]string, 0)
	if r.Age > 0 {
		profile.Age = r.Age
		profile_col = append(profile_col, "age")
	}
	if r.Sex > 0 {
		profile.Gender = r.Sex
		profile_col = append(profile_col, "gender")
	}
	if len(r.Career) > 0 {
		profile.Career = r.Career
		profile_col = append(profile_col, "career")
	}
	if r.Height > 0 {
		profile.Height = r.Height
		profile_col = append(profile_col, "height")
	}
	if r.Weight > 0 {
		profile.Weight = r.Weight
		profile_col = append(profile_col, "weight")
	}
	if len(r.City) > 0 {
		profile.City = r.City
		profile_col = append(profile_col, "city")
	}
	if len(r.Constellation) > 0 {
		profile.Constellation = r.Constellation
		profile_col = append(profile_col, "constellation")
	}
	if len(r.Signature) > 0 {
		profile.Signature = r.Signature
		profile_col = append(profile_col, "signature")
	}
	err = base.Service.EditUserInfo(user_col, profile_col, userApply, user, profile)
	if err != nil {
		return util.BuildFail(c, 1, "", err)
	}
	if r.AvatarId > 0 { //改头像
		err = cache2.OnTaskEvent(int(user.Id), _const.TASK_SET_AVATAR, 1)
		if err != nil {
			global2.Log.Infof("任务:用户%d 改名事件推送失败，任务id%d", user.Id, int(_const.TASK_SET_AVATAR), err.Error())
		}
	}

	if len(r.NickName) > 0 { //改昵称
		err = cache2.OnTaskEvent(int(user.Id), _const.TASK_SET_NICKNAME, 1)
		if err != nil {
			global2.Log.Infof("任务:用户%d 改名事件推送失败，任务id%d", user.Id, int(_const.TASK_SET_NICKNAME), err.Error())
		}
	}
	return util.BuildSuccess(c, nil, "")
}

// @Summary 忘记密码
// @Description 忘记密码
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.ForgetPwdReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/forgetPwd [POST]
func (base *Controller) ForgetPwd(c echo.Context) error {
	r := &api_models.ForgetPwdReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	msg, err := base.Service.ForgetPwd(r)
	if err != nil {
		return util.BuildFail(c, 1, msg, err)
	}
	return util.BuildSuccess(c, nil, "")
}

// @Summary 密码修改
// @Description 密码修改
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.ChangePwdReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/changePwd [POST]
func (base *Controller) ChangePwd(c echo.Context) error {

	r := &api_models.ChangePwdReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	msg, err := base.Service.ChangePwd(r, user)
	if err != nil {
		return util.BuildFail(c, 1, msg, err)
	}
	err = cache2.OnTaskEvent(user.Id, _const.TASK_SET_PASSWORD, 1)
	if err != nil {
		global2.Log.Infof("任务:推送设置密码失败:%d领取活动ID:%d失败%v", user.Id, int(_const.TASK_SET_PASSWORD), err.Error())
	}
	cache2.DelUserLastToken(user.Id) //删掉这个last token，使快速登陆失效
	return util.BuildSuccess(c, nil, "")
}

// @Summary 新增銀行卡 需登入
// @Description 新增銀行卡 需登入
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.AddBankReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/addBank [POST]
func (base *Controller) AddBank(c echo.Context) error {
	r := &api_models.AddBankReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	err = base.Service.CheckCode(user.Mobile, r.Smscode)
	if err != nil {
		return util.BuildFail(c, 1, err.Error(), err)
	}
	msg, err := base.Service.AddBank(r, user)
	if err != nil {
		return util.BuildFail(c, 1, msg, err)
	}
	return util.BuildSuccess(c, nil, "")
}

// @Summary 銀行卡列表 需登入
// @Description 銀行卡列表 需登入
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 {object} models_main.UserBank "result"
// @Router /api/user/getBanks [POST]
func (base *Controller) GetBanks(c echo.Context) error {

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}

	resp, err := base.Service.GetBanks(user)
	if err != nil {
		return util.BuildFail(c, 1, "", err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 刪除銀行卡 需登入
// @Description 刪除銀行卡 需登入
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/delBank/{id} [POST]
func (base *Controller) DelBank(c echo.Context) error {
	id := util.S2I(c.Param("id"))
	if id <= 0 {
		return util.BadParam(c, errors.New("id not exist"))
	}

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	msg, err := base.Service.DelBank(id, user)
	if err != nil {
		return util.BuildFail(c, 1, msg, err)
	}
	return util.BuildSuccess(c, nil, "")
}

// @Summary 获取粉丝信息 需登入
// @Description 获取粉丝信息 需登入
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.GetFansReq true "body"
// @Success 200 {object} api_models.GetFansResp "result"
// @Router /api/user/getFans [POST]
func (base *Controller) GetFans(c echo.Context) error {
	r := &api_models.GetFansReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	r.Page = string2.GetDefaultNum(r.Page, 1)
	r.Size = string2.GetDefaultNum(r.Size, 20)
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	resp, err := base.Service.GetFans(r, user)
	if err != nil {
		return util.BuildFail(c, 1, "", err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 手機號修改 需登入
// @Description 手機號修改 需登入
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.ChangeMobileReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/changeMobile [POST]
func (base *Controller) ChangeMobile(c echo.Context) error {
	r := &api_models.ChangeMobileReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	msg, err := base.Service.ChangeMobile(r, user)
	if err != nil {
		return util.BuildFail(c, 1, msg, err)
	}
	return util.BuildSuccess(c, nil, "")
}

// @Summary 校验验证码
// @Description 校验验证码
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.CheckVerifyCodeReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/checkSmsCode [POST]
func (base Controller) CheckSmsCode(c echo.Context) error {
	r := &api_models.CheckVerifyCodeReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	err := base.Service.CheckCode(r.Mobile, r.Smscode)
	if err != nil {
		return util.BuildFail(c, 1, err.Error(), err)
	}
	return util.BuildSuccess(c, nil, "")
}

// @Summary 支付密碼修改 需登入
// @Description 支付密碼修改 需登入
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.ChangePayPwdReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/changePayPwd [POST]
func (base *Controller) ChangePayPwd(c echo.Context) error {

	r := &api_models.ChangePayPwdReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	msg, err := base.Service.ChangePayPwd(r, user)
	if err != nil {
		return util.BuildFail(c, 1, msg, err)
	}
	return util.BuildSuccess(c, nil, "")
}

// @Summary 添加收貨地址
// @Description 添加收貨地址
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.AddAddressReq true "body"
// @Success 200 {object} nil "result"
// @Router /api/user/saveAddress [POST]
func (base *Controller) SaveAddress(c echo.Context) error {
	r := &api_models.AddAddressReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	msg, err := base.Service.SaveAddress(r, user)
	if err != nil {
		return util.BuildFail(c, 1, msg, err)
	}
	return util.BuildSuccess(c, nil, "")

}

// @Summary 获取收货地址
// @Description 获取收貨地址
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 {object} api_models.GetAddressResp "result"
// @Router /api/user/getAddress [POST]
func (base *Controller) GetAddress(c echo.Context) error {
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	addr, err := base.Service.GetUserAddress(user.Id)
	if err != nil {
		return util.BuildFail(c, 1, err.Error(), err)
	}
	return util.BuildSuccess(c, addr, "")

}

// @Summary  用户资产信息 需登入
// @Description  用户资产信息 需登入
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 {object} api_models.UserAsset "result"
// @Router /api/user/getUserAsset [POST]
func (base *Controller) GetUserAsset(c echo.Context) error {

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	resp, err := base.Service.GetUserAsset(user)
	if err != nil {
		return util.BuildFail(c, 1, "", err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary  检查主播状态，是否认证已是主播, 是否已在直播中
// @Description  检查主播状态，是否认证已是主播, 是否已在直播中
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 {object} api_models.AnchorStatus "result"
// @Router /api/user/checkAnchorStatus [POST]
func (base *Controller) CheckAnchorStatus(c echo.Context) error {

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	resp, err := base.Service.CheckAnchorStatus(user)
	if err != nil {
		return util.BuildFail(c, 1, "", err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 用户背包 需登入
// @Description 用户背包 需登入
// @Accept  json
// @Produce  json
// @Tags User
// @Router /api/user/userBackpack [POST]
func (base *Controller) UserBackpack(c echo.Context) error {
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	resp, err := base.Service.UserBackPack(user.Id)
	if err != nil {
		return util.BuildFail(c, 1, "", err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 用户反馈意见
// @Description 用户反馈意见
// @Accept  json
// @Produce  json
// @Tags Home
// @Param   sendBody body api_models.UserFeedbackReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/moment/SendFeedback [POST]
func (base *Controller) SendFeedback(c echo.Context) error {
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	r := &api_models.UserFeedbackReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	ip := c.RealIP()
	if cache2.SendApiLimit("feedback", ip, util.I2S(user.Id), 2, true) {
		return util.BuildFail(c, 1, global.Lang.T("request_frequent"), nil)
	}
	if util.GetStrLength(r.Title) > 30 {
		return util.BuildFail(c, 1, global.Lang.T("title_too_long"), nil)
	}
	if util.GetStrLength(r.Content) > 300 {
		return util.BuildFail(c, 1, global.Lang.T("content_too_long"), nil)
	}
	if util.GetStrLength(strings.TrimSpace(r.Title)) == 0 || util.GetStrLength(strings.TrimSpace(r.Content)) == 0 {
		return util.BuildFail(c, 1, global.Lang.T("title_content_not_null"), nil)
	}
	err = base.Service.SendFeedback(user.Id, r)
	if err != nil {
		return util.BuildFail(c, 1, global.Lang.T("server_internal_error"), errors.New(global.Lang.T("server_internal_error")))
	}
	return util.BuildSuccess(c, "", global.Lang.T("thank_you_for_feedback"))
}

// @Summary 获取邀请信息
// @Description 获取邀请信息
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 {object} api_models.GetInviteInfoResp "result"
// @Router /api/user/getInviteInfo [POST]
func (base *Controller) GetInviteInfo(c echo.Context) error {
	resp, err := base.Service.GetInviteInfo(uint(c.Get("uid").(int)))
	if err != nil {
		return util.BuildFail(c, 1, "", err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 领取拉新奖励
// @Description 领取拉新奖励
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/receiveReward [POST]
func (base *Controller) ReceiveReward(c echo.Context) error {
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	err = base.Service.ReceiveInvitationReward(user)
	if err != nil {
		return util.BuildFail(c, 1, err.Error(), err)
	}
	return util.BuildSuccess(c, nil, "")
}

// @Summary 注销账号
// @Description 注销账号
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.DeactiveReq true "body"
// @Success 200 {object} protobuf.DeactiveResp "result"
// @Router /api/user/deactive [POST]
func (base *Controller) Deactive(c echo.Context) error {
	r := &protobuf.DeactiveReq{}
	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	r.Uid = int32(user.Id)
	if err != nil {
		global2.Log.Errorf("%s %s\n", util.Convert2(), err.Error())
	}
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.Deactive(ctx, r)
	if err != nil {
		global2.Log.Errorf("%s %s\n", util.Convert2(), err.Error())
	}
	if r.Recall == 0 {
		//common.DelCookie(c, "token")
		//common.DelCookie(c, "uid")
		//err = cache.DelUserToken(user.Id)
		return util.BuildSuccess(c, resp, "注销成功，再见")
	} else {
		return util.BuildSuccess(c, resp, "操作成功，欢迎回来")
	}
}

// @Summary 验证验证码
// @Description 验证验证码准备进入下一步
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body protobuf.ReadyForTakeOffReq true "body"
// @Success 200 {object} protobuf.ReadyForTakeOffResp "result"
// @Router /api/user/readyForTakeOff [POST]
func (base *Controller) ReadyForTakeOff(c echo.Context) error {
	r := &protobuf.ReadyForTakeOffReq{}

	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.ReadyForTakeOff(ctx, r)
	if err != nil {
		global2.Log.Errorf("%s %s\n", util.Convert2(), err.Error())
		return util.BuildFail(c, 1, err.Error(), err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 忘记密码
// @Description 输入上一步的hash和新密码
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.ForgetPwdHashReq true "body"
// @Success 200 {object} protobuf.ForgetPwdHashResp "result"
// @Router /api/user/forgetPwdHash [POST]
func (base *Controller) ForgetPwdHash(c echo.Context) error {
	r := &protobuf.ForgetPwdHashReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.ForgetPwdHash(ctx, r)
	if err != nil {
		global2.Log.Errorf("%s %s\n", util.Convert2(), err.Error())
		return util.BuildFail(c, 1, err.Error(), err)
	}
	return util.BuildSuccess(c, resp, "")
}

// @Summary 快速登录
// @Description 快速登录
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.FastLoginReq true "body"
// @Success 200 {object} protobuf.FastLoginResp "result"
// @Router /api/user/fastLogin [POST]
func (base *Controller) FastLogin(c echo.Context) error {
	//设备拉黑
	isBlack := CheckDeviceBlackDevice(base.GetDeviceInfo(c))
	if isBlack {
		return util.BuildFail(c, 1, global.Lang.T("restrict_login"), nil)
	}
	isBlack = CheckDeviceBlackIp(c.RealIP())
	if isBlack {
		return util.BuildFail(c, 1, global.Lang.T("restrict_login"), nil)
	}

	r := &protobuf.FastLoginReq{}

	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}

	//使用黑名单设备注册的全部账户，在其他设备不可进行登陆
	isBlack = CheckAccountBlackDevice(r.Mobile)
	if isBlack {
		return util.BuildFail(c, 1, "网络超时，请稍候再试", nil)
	}

	r.Token = ""
	r.Ip = c.RealIP()
	r.DeviceInfo = base.GetDeviceInfo(c)
	if err := util.CheckMobile(r.Mobile); err == nil {
		user, errDb := mysql.GetUserParam(map[string]interface{}{"mobile": r.Mobile})
		if errDb == nil {
			r.Token, _ = cache2.GetUserLastToken(user.Id)
		}
	}
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.FastLogin(ctx, r)
	if err != nil {
		global2.Log.Infof("%s %s\n", util.Convert2(), err.Error())
		return util.BuildFail(c, 1, err.Error(), err)
	}
	return util.BuildSuccess(c, resp, "")
}

/**
 * @Author admin
 * @Description //返回腾讯签名
 * @version: v1.8.0
 * @Date 13:51 2022/8/18
 * @Param
 * @return
 **/
func getSig(ctx context.Context, userId int) string {
	r1 := &protobuf.UserSigReq{}
	r1.Id = cast.ToString(userId)

	sig, err := grpc_client.GrpcTencentImClient.GetUserSig(ctx, r1)
	if err != nil {
		global2.Log.Errorf("getSig %v", err)
		return ""
	}
	return sig.Sig
}

/**
 * @author Jared
 * @description 判断注册/登录设备是否黑名单设备
 * @createTime 11:00 2022/12/15
 **/
func CheckDeviceBlackDevice(deviceInfo string) (isBlack bool) {
	if len(deviceInfo) > 0 {
		blackDevice, _ := db_main.GetBlackDevice(map[string]interface{}{
			"device": deviceInfo,
		})
		return blackDevice.Id > 0
	}
	return
}

func CheckDeviceBlackIp(ip string) (isBlack bool) {
	if len(ip) > 0 {
		blackDevice, _ := db_main.GetBlackIp(map[string]interface{}{
			"ip": ip,
		})
		return blackDevice.Id > 0
	}
	return
}

/**
 * @author Jared
 * @description 判断登录账户是否黑名单设备
 * @createTime 11:00 2022/12/15
 **/
func CheckAccountBlackDevice(account string) (isBlack bool) {
	if len(account) > 0 {
		u, err := mysql.GetUserParam(map[string]interface{}{
			"account": account,
		})
		if err != nil {
			return
		}
		if u.Id <= 0 {
			return
		}
		if len(u.DeviceInfo) <= 0 {
			return
		}
		bDevice, _ := db_main.GetBlackDevice(map[string]interface{}{
			"device": u.DeviceInfo,
		})
		return bDevice.Id > 0
	}
	return
}

// @Summary 简化注册 密码注册
// @Description 简化注册 密码注册
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.RegisterReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/simple_regist [POST]
func (base *Controller) SimpleRegist(c echo.Context) error {
	req := &api_models.SimpleRegisterReq{}

	if err := util.Json2Struct(c.Get("body").(string), req); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(req); err != nil {
		return util.BadParam(c, err)
	}
	global2.Log.Debugf("heardDevice:%v,bodyDevice:%v", base.GetDeviceInfo(c), req.DeviceInfo)
	r := &protobuf.RegisterReq{
		Account:  req.Account,
		Pwd:      req.Pwd,
		Platform: uint32(req.Platform),
		// Sex:      uint32(req.Sex),
		Sex: 1, // 产品需求默认男性

		InviteCode: req.InviteCode,
		Ip:         c.RealIP(),
		DeviceInfo: base.GetDeviceInfo(c), //req.DeviceInfo,

		Website:  req.Website,
		AnchorId: req.AnchorId,
	}
	switch req.RegSourceId.(type) { //动态类型
	case int, float64:
		r.RegSourceId = fmt.Sprint(req.RegSourceId)
	case string:
		r.RegSourceId = req.RegSourceId.(string)
	}
	//fixme Platform
	ctx, cancel := base.GrpcWithTimeout()
	defer cancel()
	resp, err := grpc_client.GrpcAccountServer.SimpleRegister(ctx, r)
	if err != nil {
		statsErr := status.Convert(err)
		return util.BuildFail(c, 1, statsErr.Message(), err)
	}

	util.SetCookie(c, "token", resp.Token)
	util.SetCookie(c, "uid", cast.ToString(resp.Id))
	err = cache2.SetUserToken(int(resp.Id), resp.Token, req.Platform)
	if err != nil {
		global2.Log.Errorf("set token error[%v]: ", err)
	}
	err = cache2.OnTaskEvent(int(resp.Id), _const.TASK_SIGN_UP, 1) //注册成功事件
	if err != nil {
		global2.Log.Infof("任务:推送注册事件失败%d, %d, %v", resp.Id, int(_const.TASK_SIGN_UP), err.Error())
	}
	if r.Platform != 0 { //
		err = cache2.OnTaskEvent(int(resp.Id), _const.TASK_SIGN_IN_APP, 1) //首次登陆app事件
		if err != nil {
			global2.Log.Infof("任务:推送App登陆事件失败%d领取活动ID:%d失败,%v", resp.Id, int(_const.TASK_SIGN_IN_APP), err.Error())
		}
		err = cache2.OnTaskEvent(int(resp.Id), _const.TASK_SIGN_IN_EVERYDAY, 1) //每日登陆app事件
		if err != nil {
			global2.Log.Infof("任务:推送App登陆事件失败%d领取活动ID:%d失败,%v", resp.Id, int(_const.TASK_SIGN_IN_EVERYDAY), err.Error())
		}
	}

	// 推送使用统计
	err = global2.PublisherStatistic.StatisticPush(
		publisher.RegisterStatistic, int(resp.Id), req.DeviceInfo, c.RealIP(), int8(req.Platform),
	)
	if err != nil {
		global2.Log.Infof("stats error: %v", err)
	}
	//增加腾讯 sig 调用
	resp.Sig = getSig(ctx, int(resp.Id))

	// 弹窗统计
	var dr api_models.ActionReq
	util.Json2Struct(c.Get("body").(string), &dr)

	if dr.Desc != "" {
		var d models_main.DialogConfig
		err = global.GetR().Model(&d).Where("status=1").First(&d).Error
		if err != nil {
			global2.Log.Infof("dialog_config error: %v", err)
		}
		err = global.GetX().Model(&d).Where("id=?", d.ID).Update("reg_count", gorm.Expr("reg_count+1")).Error
		if err != nil {
			global2.Log.Infof("dialog_config error: %v", err)
		}
	}

	return util.BuildSuccess(c, resp, "")
}

// @Summary 检查绑定6T账号状态
// @Description 检查绑定6T账号状态
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/checkBindAccount [POST]
func (base *Controller) CheckBindAccount(c echo.Context) error {

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	resp, err := base.Service.CheckBindAccount(user)
	if err != nil {
		return util.BuildFail(c, 1, err.Error(), err)
	}

	return util.BuildSuccess(c, resp, "")
}

// @Summary 绑定6T账号
// @Description 绑定6T账号
// @Accept  json
// @Produce  json
// @Tags User
// @Param   sendBody body api_models.BindAccountReq true "body"
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/bindAccount [POST]
func (base *Controller) BindAccount(c echo.Context) error {

	r := &api_models.BindAccountReq{}
	if err := util.Json2Struct(c.Get("body").(string), r); err != nil {
		return util.BadParam(c, err)
	}
	if err := _const.Validate.Struct(r); err != nil {
		return util.BadParam(c, err)
	}

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	msg, err := base.Service.AddBindAccount(r, user)
	if err != nil {
		return util.BuildFail(c, 1, msg, err)
	}

	return util.BuildSuccess(c, nil, "")
}

// @Summary 解绑6T账号
// @Description 解绑6T账号
// @Accept  json
// @Produce  json
// @Tags User
// @Success 200 {object} api_models.Response "result"
// @Router /api/user/unbindAccount [POST]
func (base *Controller) UnbindAccount(c echo.Context) error {

	user, err := base.GetUserByCtx(c)
	if err != nil {
		return util.BuildLoginTimeOut(c, err)
	}
	msg, err := base.Service.UnbindAccount(user)
	if err != nil {
		return util.BuildFail(c, 1, msg, err)
	}

	return util.BuildSuccess(c, nil, "")
}
